package com.tuniu.agents.tools.train.tool;

import com.fasterxml.jackson.annotation.JsonClassDescription;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import com.tuniu.agents.advisor.ChatEnvironmentMemory;
import com.tuniu.agents.message.ToolLoggerInfo;
import com.tuniu.agents.tools.train.TrainProperties;
import com.tuniu.agents.tools.train.constants.TrainCommonConstants;
import com.tuniu.agents.tools.train.model.TrainDetailLinkData;
import com.tuniu.agents.tools.train.model.TrainMPOrderLinkData;
import com.tuniu.agents.tools.train.utils.TrainCommonUtil;
import com.tuniu.agents.util.HttpManager;
import com.tuniu.agents.util.I18nUtil;
import com.tuniu.agents.util.JsonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.model.ToolContext;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

import static com.tuniu.agents.tools.train.TrainProperties.KEY_NAME;
import static com.tuniu.agents.tools.train.constants.TrainCommonConstants.APP_TRAIN_DETAIL_URL;
import static com.tuniu.agents.tools.train.constants.TrainCommonConstants.SEAT_DETAIL_PRICE_DESC;

public class SearchTrainDetailTool implements BiFunction<SearchTrainDetailTool.Request, ToolContext, SearchTrainDetailTool.Response> {

    private static final Logger logger = LoggerFactory.getLogger(SearchTrainDetailTool.class);

    public static final String TOOLNAME = "search_train_detail";

    protected final String searchTrainDetailUrl;

    private final String accessKey;

    @Autowired
    private HttpManager httpManager;

    @Autowired
    private ChatMemory chatMemory;

    @Autowired(required = false)
    private ChatEnvironmentMemory chatEnvironmentMemory;

    public SearchTrainDetailTool(TrainProperties properties) {
        this.searchTrainDetailUrl = properties.getSearchTrainDetailUrl();
        this.accessKey = properties.getAccessKey();
    }

    @ToolLoggerInfo
    @Override
    public Response apply(Request request, ToolContext toolContext) {
        String conversationId = (String)toolContext.getContext().get("conversation_id");
        logger.info("SearchTrainDetailTool apply conversationId:{}, request:{}",conversationId, JsonUtil.toJson(request));

        //get conversationId
        Map<String,Object> map = toolContext.getContext();
        //Get train information from environment variables
        String trainJsonInfo = JsonUtil.toJson(chatEnvironmentMemory.get((String) map.get("conversation_id")).get(request.trainNum));
        Request requestFromCache = JsonUtil.fromJson(trainJsonInfo,Request.class);

        if(requestFromCache != null) {
            request = new Request(
                    requestFromCache.departureStationName(),
                    requestFromCache.arrivalStationName(),
                    requestFromCache.departureDate(),
                    request.trainNum()
            );
        }

        //Get train detail information
        try {
            logger.info("SearchTrainDetailTool apply realInfo conversationId:{}, request:{}",conversationId, JsonUtil.toJson(request));
            Response response = httpManager.post(searchTrainDetailUrl, request, Response.class,Map.of(KEY_NAME,accessKey));

            if(!response.success() || response.data() == null){
                logger.error("SearchTrainDetailTool apply fail or empty conversationId:{}, request:{},response:{}",conversationId, JsonUtil.toJson(request),JsonUtil.toJson(response));
                return null;
            }
            return response;
        }catch (Exception e){
            logger.error("SearchTrainDetailTool apply error conversationId:{}, request:{}", conversationId, JsonUtil.toJson(request),e);
            return null;
        }

    }


    @JsonClassDescription("Train ticket detail query parameters")
    public record Request(
            @JsonProperty(value = "departureStationName")
            @JsonPropertyDescription("Departure station name, cannot be the same as arrivalStationName")
            String departureStationName,

            @JsonProperty(value = "arrivalStationName")
            @JsonPropertyDescription("Arrival station name, cannot be the same as departureStationName")
            String arrivalStationName,

            @JsonProperty(value = "departureDate")
            @JsonPropertyDescription("Departure date in yyyy-MM-dd format")
            String departureDate,

            @JsonProperty(value = "trainNum",required = true)
            @JsonPropertyDescription("Train number")
            String trainNum
    ) {
    }

    @JsonClassDescription("Train ticket detail response data")
    public record Response(
            @JsonProperty( value = "success") @JsonPropertyDescription("Success or failure flag")
            boolean success,

            @JsonProperty( value = "errorCode") @JsonPropertyDescription("Error code")
            int errorCode,

            @JsonProperty( value = "msg") @JsonPropertyDescription("Error message")
            String msg,

            @JsonProperty( value = "data") @JsonPropertyDescription("Train information")
            TrainDetailData data
    ) {
    }

    public record TrainDetailData(
            @JsonProperty( value = "isVoucherSaleForDetail") @JsonPropertyDescription("Has detail voucher")
            boolean isVoucherSaleForDetail,

            @JsonProperty( value = "isVoucherSaleForGrab") @JsonPropertyDescription("Has grab voucher")
            String isVoucherSaleForGrab,

            @JsonProperty( value = "trainInfo") @JsonPropertyDescription("Train information")
            TrainInfo trainInfo,

            @JsonProperty( value = "seatInfo") @JsonPropertyDescription("Seat information")
            List<SeatInfo> seatInfo,

            @JsonProperty( value = "isOpen") @JsonPropertyDescription("Is open")
            int isOpen,

            @JsonProperty( value = "needAdd") @JsonPropertyDescription("Needs addition")
            boolean needAdd,

            @JsonProperty( value = "departureDates") @JsonPropertyDescription("Departure dates")
            DepartureDates departureDates,

            @JsonProperty( value = "couponsConfig") @JsonPropertyDescription("Coupon configuration")
            CouponsConfig couponsConfig,

            @JsonProperty( value = "isSupportVoucherSection") @JsonPropertyDescription("Supports voucher")
            boolean isSupportVoucherSection
    ) {
    }

    public record TrainInfo(
            @JsonProperty( value = "id") @JsonPropertyDescription("Id")
            String id,

            @JsonProperty( value = "trainId") @JsonPropertyDescription("Train Id")
            String trainId,

            @JsonProperty( value = "trainNum") @JsonPropertyDescription("Train number")
            String trainNum,

            @JsonProperty( value = "trainType") @JsonPropertyDescription("Train type")
            String trainType,

            @JsonProperty( value = "trainTypeCode") @JsonPropertyDescription("Train type code")
            Integer trainTypeCode,

            @JsonProperty( value = "trainTypeName") @JsonPropertyDescription("Train type name")
            String trainTypeName,

            @JsonProperty( value = "departureCityName") @JsonPropertyDescription("Departure city")
            String departureCityName,

            @JsonProperty( value = "departCityId") @JsonPropertyDescription("Departure city code")
            String departCityId,

            @JsonProperty( value = "arrivalCityName") @JsonPropertyDescription("Arrival city code")
            String arrivalCityName,

            @JsonProperty( value = "destCityId") @JsonPropertyDescription("Destination city code")
            String destCityId,

            @JsonProperty( value = "departStationName") @JsonPropertyDescription("Departure station name")
            String departStationName,

            @JsonProperty( value = "destStationCode") @JsonPropertyDescription("Destination station code")
            String destStationCode,

            @JsonProperty( value = "departStationType") @JsonPropertyDescription("Departure station type (过路、始发、终点)")
            String departStationType,

            @JsonProperty( value = "departStationCode") @JsonPropertyDescription("Departure station code")
            String departStationCode,

            @JsonProperty( value = "departStationTypeCode") @JsonPropertyDescription("Departure station type code")
            Integer departStationTypeCode,

            @JsonProperty( value = "destStationName") @JsonPropertyDescription("Destination station name")
            String destStationName,

            @JsonProperty( value = "destStationType") @JsonPropertyDescription("Destination station type")
            String destStationType,

            @JsonProperty( value = "destStationTypeCode") @JsonPropertyDescription("Destination station type code")
            Integer destStationTypeCode,

            @JsonProperty( value = "departTime") @JsonPropertyDescription("Departure time HH:mm")
            String departTime,

            @JsonProperty( value = "arriveTime") @JsonPropertyDescription("Arrival time HH:mm")
            String arriveTime,

            @JsonProperty( value = "saleStatus") @JsonPropertyDescription("Sale status")
            String saleStatus,

            @JsonProperty( value = "saleStatusId") @JsonPropertyDescription("Sale status Id")
            Integer saleStatusId,

            @JsonProperty( value = "duration") @JsonPropertyDescription("Journey duration")
            String duration,

            @JsonProperty( value = "durationDay") @JsonPropertyDescription("Journey days")
            int durationDay,

            @JsonProperty( value = "departsDate") @JsonPropertyDescription("Departure date yyyy-MM-dd")
            String departsDate,

            @JsonProperty( value = "arriveDate") @JsonPropertyDescription("Arrival date yyyy-MM-dd")
            String arriveDate,

            @JsonProperty( value = "memoDay") @JsonPropertyDescription("Memo days")
            String memoDay,

            @JsonProperty( value = "memoHour") @JsonPropertyDescription("Memo hours")
            String memoHour,

            @JsonProperty( value = "departureDates") @JsonPropertyDescription("Departure dates")
            DepartureDates departureDates,

            @JsonProperty( value = "leftNumber") @JsonPropertyDescription("Available tickets")
            int leftNumber,

            @JsonProperty( value = "seat") @JsonPropertyDescription("Seat class")
            String seat,

            @JsonProperty( value = "price") @JsonPropertyDescription("Price")
            String price,
            
            @JsonProperty( value = "promotionPrice") @JsonPropertyDescription("Promotion price")
            String promotionPrice,

            @JsonProperty( value = "resId") @JsonPropertyDescription("Resource Id")
            Integer resId,

            @JsonProperty( value = "canGrap") @JsonPropertyDescription("Can grab ticket")
            Boolean canGrap,

            @JsonProperty( value = "oneLeftNumber") @JsonPropertyDescription("One left number")
            Integer oneLeftNumber,

            @JsonProperty( value = "supportSeatSelection") @JsonPropertyDescription("Supports seat selection")
            Boolean supportSeatSelection,

            @JsonProperty( value = "supportIdCheckin") @JsonPropertyDescription("Supports Id Card check-in")
            Boolean supportIdCheckin,

            @JsonProperty( value = "supportTransferFlag") @JsonPropertyDescription("Supports same-train seat transfer")
            Boolean supportTransferFlag

    ) {
        public TrainInfo{
            price = TrainCommonUtil.formatPrice(price);
            promotionPrice = TrainCommonUtil.formatPrice(promotionPrice);
        }
    }

    public record SeatInfo(
            @JsonProperty( value = "leftNumber") @JsonPropertyDescription("Available seats")
            int leftNumber,

            @JsonProperty( value = "leftNumberDesc") @JsonPropertyDescription("Available seats description")
            String leftNumberDesc,

            @JsonProperty( value = "seatId") @JsonPropertyDescription("Seat class Id")
            Integer seatId,

            @JsonProperty( value = "seatName") @JsonPropertyDescription("Seat class name")
            String seatName,

            @JsonProperty( value = "price") @JsonPropertyDescription("Price")
            String price,

            @JsonProperty( value = "adultPrice") @JsonPropertyDescription("Adult price")
            String adultPrice,

            @JsonProperty( value = "promotionPrice") @JsonPropertyDescription("Promotion price")
            String promotionPrice,

            @JsonProperty( value = "resId") @JsonPropertyDescription("Resource Id")
            long resId,

            @JsonProperty( value = "seatStatus") @JsonPropertyDescription("Seat status")
            String seatStatus,

            @JsonProperty( value = "seatSequence") @JsonPropertyDescription("Seat sequence")
            Integer seatSequence,

            @JsonProperty( value = "lowestPrice") @JsonPropertyDescription("Lowest price")
            String lowestPrice,

            @JsonProperty( value = "isConfigSeat") @JsonPropertyDescription("Delivery ticket entrance is open")
            boolean isConfigSeat,

            @JsonProperty( value = "configSeatInfo") @JsonPropertyDescription("Delivery ticket entrance information")
            Object configSeatInfo,

            @JsonProperty( value = "isSupportVoucherSection") @JsonPropertyDescription("Supports voucher section")
            boolean isSupportVoucherSection,

            @JsonProperty( value = "trainVoucherInfo") @JsonPropertyDescription("Train voucher information")
            List<Object> trainVoucherInfo,

            @JsonProperty( value = "url") @JsonPropertyDescription("Booking page link")
            SearchAllTrainTool.TrainOrderUrl url
    ) {
        public SeatInfo{
            price = TrainCommonUtil.formatPrice(price);
            adultPrice = TrainCommonUtil.formatPrice(adultPrice);
            promotionPrice = TrainCommonUtil.formatPrice(promotionPrice);
            lowestPrice = TrainCommonUtil.formatPrice(lowestPrice);
        }

        public SeatInfo withUrlAndChangeLeftNum(SearchAllTrainTool.TrainOrderUrl newUrl,String conversationId) {
            String leftNumberDesc = null;
            // If available tickets > 50, mark as sufficient
            leftNumberDesc = leftNumber == 0 ? I18nUtil.getMessage(conversationId,TrainCommonConstants.SEAT_DETAIL_EMPTY_TAG) :leftNumber > 50 ? I18nUtil.getMessage(conversationId,TrainCommonConstants.SEAT_ENOUGH_TAG) : I18nUtil.getMessage(conversationId,TrainCommonConstants.SEAT_LEFT_NUM,new Object[]{leftNumber});
            return new SeatInfo(
                    this.leftNumber,
                    leftNumberDesc,
                    this.seatId,
                    this.seatName,
                    this.price,
                    this.adultPrice,
                    this.promotionPrice,
                    this.resId,
                    this.seatStatus,
                    this.seatSequence,
                    this.lowestPrice,
                    this.isConfigSeat,
                    this.configSeatInfo,
                    this.isSupportVoucherSection,
                    this.trainVoucherInfo,
                    newUrl
            );
        }
    }

    public record DepartureDates(
            @JsonProperty( value = "yesterday") @JsonPropertyDescription("Yesterday")
            String yesterday,

            @JsonProperty( value = "today") @JsonPropertyDescription("Today")
            String today,

            @JsonProperty( value = "tomorrow") @JsonPropertyDescription("Tomorrow")
            String tomorrow
    ) {
    }

    public record CouponsConfig(
            @JsonProperty( value = "displaySwitch") @JsonPropertyDescription("Display switch")
            boolean displaySwitch,

            @JsonProperty( value = "recommendText") @JsonPropertyDescription("Recommendation text")
            String recommendText
    ) {
    }

    /**
     * Build train ticket detail card
     * @param response
     * @return
     */
    public static TrainDetailData buildDetailCardInfo(Response response,String conversationId){
        TrainDetailData trainDetailData = response.data;
        try {
            // Convert detail information to app jump link required data
            TrainDetailLinkData trainDetailLinkData = convertToTrainDetailData(response);
            String json = JsonUtil.toJson(trainDetailLinkData);

            // Build appUrl
            String appUrl = null;
            try {
                String parameters = URLEncoder.encode(json, "UTF-8");
                appUrl = APP_TRAIN_DETAIL_URL + parameters;
            } catch (UnsupportedEncodingException e) {
                logger.warn("SearchTrainDetailTool getDetailCardInfo error encoding parameters", e);
            }
            SearchAllTrainTool.TrainOrderUrl trainOrderUrl = new SearchAllTrainTool.TrainOrderUrl(appUrl, null, null);

            // Update url in seatInfo list and sort train seats by price
            List<SeatInfo> updatedSeatInfo = trainDetailData.seatInfo().stream()
                    .map(seatInfo -> {
                        // Get MPUrl for each seat class
                        String mpUrl = buildMPOrderData(trainDetailData, seatInfo);
                        SearchAllTrainTool.TrainOrderUrl trainOrderUrlNew = trainOrderUrl.withUrl(null,mpUrl);
                        return seatInfo.withUrlAndChangeLeftNum(trainOrderUrlNew,conversationId);

                    }).sorted((s1, s2) -> {
                        try {
                            BigDecimal price1 = new BigDecimal(s1.price());
                            BigDecimal price2 = new BigDecimal(s2.price());
                            return price2.compareTo(price1);  // Sort in descending order
                        } catch (NumberFormatException e) {
                            logger.warn("SearchTrainDetailTool getDetailCardInfo price parse error: s1={}, s2={}", s1.price(), s2.price());
                            return 0; // Keep original order when conversion fails
                        }
                    })
                    .collect(Collectors.toList());

            // Create new TrainDetailData object
            return new TrainDetailData(
                    trainDetailData.isVoucherSaleForDetail(),
                    trainDetailData.isVoucherSaleForGrab(),
                    trainDetailData.trainInfo(),
                    updatedSeatInfo,
                    trainDetailData.isOpen(),
                    trainDetailData.needAdd(),
                    trainDetailData.departureDates(),
                    trainDetailData.couponsConfig(),
                    trainDetailData.isSupportVoucherSection());
        } catch (Exception e) {
            logger.warn("SearchTrainDetailTool getDetailCardInfo build Url fail trainTicket:{}", JsonUtil.toJson(response), e);
            return null;
        }
    }


    /**
     * Build mini program jump data
     * @param trainDetailData Train detail data
     * @param currentSeat Current seat information
     * @return Mini program jump link
     */
    private static String buildMPOrderData(TrainDetailData trainDetailData, SeatInfo currentSeat) {
        try {
            TrainInfo trainInfo = trainDetailData.trainInfo();
            TrainMPOrderLinkData trainMPOrderLinkData = new TrainMPOrderLinkData();
            trainMPOrderLinkData.setUpdate(false);
            trainMPOrderLinkData.setInitIndex(0);
            trainMPOrderLinkData.setDepartDate(trainInfo.departsDate());

            // Build train information
            List<TrainMPOrderLinkData.TrainInfo> selectList = new ArrayList<>();
            TrainMPOrderLinkData.TrainInfo mpTrainInfo = new TrainMPOrderLinkData.TrainInfo();

            // Basic information conversion
            mpTrainInfo.setTrainId(Integer.parseInt(trainInfo.trainId()));
            mpTrainInfo.setTrainNum(trainInfo.trainNum());
            mpTrainInfo.setTrainTypeCode(trainInfo.trainTypeCode());
            mpTrainInfo.setTrainTypeName(trainInfo.trainTypeName());
            mpTrainInfo.setDepartStationName(trainInfo.departStationName());
            mpTrainInfo.setDepartStationCode(trainInfo.departStationCode());
            mpTrainInfo.setDestStationName(trainInfo.destStationName());
            mpTrainInfo.setDestStationCode(trainInfo.destStationCode());
            mpTrainInfo.setDepartureCityCode(trainInfo.departCityId());
            mpTrainInfo.setArrivalCityCode(trainInfo.destCityId());
            mpTrainInfo.setDepartureCityName(trainInfo.departureCityName());
            mpTrainInfo.setDepartureCityName2(trainInfo.departureCityName());
            mpTrainInfo.setArrivalCityName(trainInfo.arrivalCityName());
            mpTrainInfo.setArrivalCityName2(trainInfo.arrivalCityName());
            mpTrainInfo.setDepartDepartTime(trainInfo.departTime());
            mpTrainInfo.setDestArriveTime(trainInfo.arriveTime());
            mpTrainInfo.setDuration(trainInfo.duration());
            mpTrainInfo.setDurationDay(trainInfo.durationDay());
            mpTrainInfo.setDepartStationType(trainInfo.departStationType());
            mpTrainInfo.setDepartStationTypeCode(trainInfo.departStationTypeCode());
            mpTrainInfo.setDestStationType(trainInfo.destStationType());
            mpTrainInfo.setDestStationTypeCode(trainInfo.destStationTypeCode());
            mpTrainInfo.setSaleStatus(trainInfo.saleStatus());
            mpTrainInfo.setSaleStatusId(trainInfo.saleStatusId());

            // Build seat description list (only includes current seat)
            List<TrainMPOrderLinkData.SeatDesc> mpSeatDescList = new ArrayList<>();
            TrainMPOrderLinkData.SeatDesc mpSeatDesc = new TrainMPOrderLinkData.SeatDesc();
            mpSeatDesc.setLeftNumber(currentSeat.leftNumber());
            mpSeatDesc.setSeatId(currentSeat.seatId());
            mpSeatDesc.setSeatName(currentSeat.seatName());
            mpSeatDesc.setPrice(currentSeat.price());
            mpSeatDesc.setAdultPrice(currentSeat.adultPrice());
            mpSeatDesc.setPromotionPrice(currentSeat.promotionPrice());
            mpSeatDesc.setResId(currentSeat.resId());
            mpSeatDesc.setSeatStatus(currentSeat.seatStatus());
            mpSeatDesc.setSeatSequence(currentSeat.seatSequence());
            mpSeatDesc.setLowestPrice(currentSeat.lowestPrice());
            mpSeatDescList.add(mpSeatDesc);
            mpTrainInfo.setSeatDesc(mpSeatDescList);

            // Set current seat information
            mpTrainInfo.setLeftNumber(currentSeat.leftNumber());
            mpTrainInfo.setSeat(currentSeat.seatName());
            mpTrainInfo.setPrice(currentSeat.price());
            mpTrainInfo.setPromotionPrice(currentSeat.promotionPrice());
            mpTrainInfo.setResId(trainInfo.resId());

            // Set other information
            mpTrainInfo.setMemoDay(trainInfo.memoDay());
            mpTrainInfo.setMemoHour(trainInfo.memoHour());
            mpTrainInfo.setCanGrap(trainInfo.canGrap());
            mpTrainInfo.setOneLeftNumber(trainInfo.oneLeftNumber());
            mpTrainInfo.setSupportSeatSelection(trainInfo.supportSeatSelection());
            mpTrainInfo.setSupportIdCheckin(trainInfo.supportIdCheckin());

            selectList.add(mpTrainInfo);
            trainMPOrderLinkData.setSelect(selectList);

            return TrainCommonConstants.MP_TRAIN_ORDER_URL + URLEncoder.encode(JsonUtil.toJson(trainMPOrderLinkData), "UTF-8");
        } catch (Exception e) {
            logger.error("SearchTrainDetailTool building mpUrl error trainDetailData:{},currentSeat:{}",JsonUtil.toJson(trainDetailData),JsonUtil.toJson(currentSeat), e);
            return null;
        }
    }

    // Extract basic information from detail information and convert to markdown format
    public static String convertDetailDataToMark(TrainDetailData detailData,String conversationId) {
        if (detailData == null || detailData.trainInfo() == null) {
            return JsonUtil.toJson(detailData);
        }

        StringBuilder resultBuilder = new StringBuilder();
        // Table header
        resultBuilder.append("| 车次号 | 车型 | 出发站 | 到达站 | 出发时间 | 到达时间 | 运行耗时 | 座位信息 |\n");
        resultBuilder.append("|--------|------|--------|--------|----------|----------|----------|----------|\n");

        // Process seat information
        StringBuilder seatInfoBuilder = new StringBuilder();
        if (detailData.seatInfo() != null && !detailData.seatInfo().isEmpty()) {
            String stationDesc = I18nUtil.getMessage(conversationId, "train.template.station.desc");

            for (SeatInfo seat : detailData.seatInfo()) {
                seatInfoBuilder.append(I18nUtil.getMessage(conversationId,SEAT_DETAIL_PRICE_DESC,new Object[]{
                        seat.seatName(),
                        seat.price(),
                        seat.leftNumber()
                }));
            }

            // Generate row data
            TrainInfo trainInfo = detailData.trainInfo();
            resultBuilder
                    .append("|").append(trainInfo.trainNum())
                    .append("|").append(trainInfo.trainTypeName())
                    .append("|").append(trainInfo.departStationName()+stationDesc)
                    .append("|").append(trainInfo.destStationName()+stationDesc)
                    .append("|").append(trainInfo.departsDate +" " + trainInfo.departTime())
                    .append("|").append(trainInfo.arriveDate + " " + trainInfo.arriveTime())
                    .append("|").append(trainInfo.duration())
                    .append("|").append(!seatInfoBuilder.isEmpty() ? seatInfoBuilder.toString() : "-")
                    .append("|\n");

            return resultBuilder.toString();
        }
        return JsonUtil.toJson(detailData);
    }


    /**
     * Convert detail information to data required for app detail page jump
     * @param response
     * @return
     */
    public static TrainDetailLinkData convertToTrainDetailData(Response response) {
        TrainDetailLinkData data = new TrainDetailLinkData();
        TrainDetailLinkData.Detail detail = new TrainDetailLinkData.Detail();
        TrainInfo trainInfo = response.data.trainInfo;

        detail.setTrainId(trainInfo.trainId());
        detail.setTrainNum(trainInfo.trainNum());
        detail.setDepartStationName(trainInfo.departStationName());
        detail.setDepartStationCode(trainInfo.departStationCode());
        detail.setDestStationName(trainInfo.destStationName());
        detail.setDestStationCode(trainInfo.destStationCode());
        detail.setDepartDepartTime(trainInfo.departTime());
        detail.setDestArriveTime(trainInfo.arriveTime());
        detail.setDuration(trainInfo.duration());
        detail.setDurationDay(trainInfo.durationDay());

        detail.setSupportSeatSelection(trainInfo.supportSeatSelection());
        detail.setSupportTransferFlag(trainInfo.supportTransferFlag());

        data.setDetail(detail);
        data.setDepartDate(trainInfo.departsDate());
        data.setDepartCityCode(trainInfo.departCityId());
        data.setDepartCityName(trainInfo.departureCityName());
        data.setDestCityCode(trainInfo.destCityId());
        data.setDestCityName(trainInfo.arrivalCityName());

        return data;
    }
}
